package pers.gxm.shiro.configuration;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AllSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pers.gxm.shiro.realm.MyRealm;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

@Configuration
public class ShiroConfig {
    @Autowired
    private MyRealm myRealm;

    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(){
//        TODO 1 创建defaultWebSecurityManager对象
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

//        TODO 2 创建加密对象，并设置相关属性
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//        加密算法
        matcher.setHashAlgorithmName("md5");
//        迭代加密次数
        matcher.setHashIterations(3);
//        TODO 3 加密对象存入myRealm中
        myRealm.setCredentialsMatcher(matcher);
//        TODO 4 myRealm存入defaultWebSecurityManager中,滞后处理
//        defaultWebSecurityManager.setRealm(myRealm);


//        TODO A 创建认证对象，并且设置认证策略
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
        defaultWebSecurityManager.setAuthenticator(modularRealmAuthenticator);
//        TODO B 封装realm集合，并存入defaultWebSecurityManager中
        ArrayList realms = new ArrayList();
        realms.add(myRealm);
        defaultWebSecurityManager.setRealms(realms);
//        TODO C 设置rememberMe
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
//        TODO 设置缓存管理器
        defaultWebSecurityManager.setCacheManager(getEhCacheManager());
        return defaultWebSecurityManager;
    }

    private EhCacheManager getEhCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        InputStream is ;
        try {
            is  = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        CacheManager cacheManager = new CacheManager(is);
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    @Bean
    public DefaultShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
//        设置不认证可以访问的登录请求
        definition.addPathDefinition("/myController/userLogin","anon");
//        设置不认证可以访问的登录页面
        definition.addPathDefinition("/myController/login","anon");
//        设置静态资源--错误示范
//        definition.addPathDefinition("/templates/login.html","anon");
        //        设置登出过滤器,要放在后两个过滤器之前
        definition.addPathDefinition("/logout","logout");

//        设置需要进行登录认证的拦截范围
        definition.addPathDefinition("/**","authc");

//        设置rememberMe专属过滤器
        definition.addPathDefinition("/**","user");

        return definition;

    }

    //cookie 属性设置
    public SimpleCookie rememberMeCookie(){
        SimpleCookie cookie = new SimpleCookie("rememberMe");
// 设置跨域
//cookie.setDomain(domain);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30*24*60*60);
        return cookie;
    }
    // 创建 Shiro 的 cookie 管理对象
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new
                CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        cookieRememberMeManager.setCipherKey("1234567890987654".getBytes());
        return cookieRememberMeManager;
    }

//    用于解析 thymeleaf 中的 shiro:相关属性
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}
